`timescale 1ns / 1ps
/*
 Copyright 2020 Sean Xiao, jxzsxsp@qq.com
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
 http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

module D_sram
#( 
    parameter MEM_D_DEEP    = 1024, //memory data depth
    parameter MEM_D_W       = 32,   //memory data width
    parameter MEM_MSK_W     = 4,    //memory data mask width
    parameter MEM_ADDR_W    = 32    //memory address width
)
(
    input  clk,
    
    input  [ MEM_D_W - 1 : 0 ] din,
    input  [ MEM_ADDR_W - 1 : 0 ] addr,
    output [ MEM_ADDR_W - 1 : 0 ] o_D_PC,
    
    input  cs,
    input  we,
    input  [ MEM_MSK_W - 1: 0 ] wem,
//output  reg                    mem_init_rdy,
    output [ MEM_D_W - 1: 0 ] dout,

    input  rst_n
);

//===============================================================================
reg  [ MEM_D_W - 1: 0 ] mem_r[ 0: MEM_D_DEEP - 1 ];
//===============================================================================
wire ren = cs & ( ~we );
wire [ MEM_MSK_W - 1: 0 ] wen = ( { MEM_MSK_W{ cs & we } } & wem );

reg  [ MEM_ADDR_W - 1: 0 ] addr_r = 0;
always @( posedge clk )
    addr_r <= addr;

wire [ MEM_ADDR_W - 1: 0 ] addr_mem = {addr[31:2]};
    
// integer                 mem_init_addr;
//===============================================================================
genvar wi;
generate
    for ( wi = 0; wi < MEM_MSK_W; wi = wi + 1 )
    begin: mem_write
        always @( posedge clk )
        begin
            if ( wen[ wi ] )
            begin
                mem_r[ addr_mem ][ 8 * wi + 7: 8 * wi ] <= din[ 8 * wi + 7: 8 * wi ];
            end
        end
    end
endgenerate
//===============================================================================
wire [ MEM_D_W - 1: 0 ] dout_pre;
wire [ MEM_D_W - 1: 0 ] dout_w;
//assign dout_pre = mem_r[ addr_r ];
assign dout_pre = mem_r[ addr_mem ];

genvar ri;
generate
    for ( ri = 0; ri < MEM_D_W; ri = ri + 1 )
    begin: mem_read
`ifdef SIM//{
        assign dout_w[ ri ] = ( dout_pre[ ri ] === 1'bx ) ? 1'b0 : dout_pre[ ri ];
`else //}{
        assign dout_w[ ri ] = dout_pre[ ri ];
`endif//}
    end
endgenerate
//===============================================================================
//wire [4:0] data_sft = addr[1:0] * 8;
wire [4:0] data_sft = {addr[1:0], 3'b000};
assign dout = dout_w >> data_sft;

assign o_D_PC = addr_r;
//===============================================================================

endmodule
